// 日志文件
// 传入的大致分为日志等级（日志本身输出时间）[左]、自定义内容（如错误码的提示）[右]
#pragma once

#include <stdarg.h>
#include <cstdio>
#include <string>
#include <iostream>
#include <time.h>
#include <ctime>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

#define SIZE 1024

#define LogFile "log.txt"
#define LocalPath "./Log/"

#define Info 0
#define Warning 1
#define Error 2
#define Fatal 3
#define Debug 4

#define Print 1
#define InputFile 2
#define ClassFile 3

using namespace std;

class Log
{
public:
    Log(const string &Path = LocalPath, int mode = Print)
    :path(Path)
    ,logmode(mode)
    {}
    

    void enable(int method)
    {
        logmode = method;
    }

    ~Log()
    {
    }

    // 将输入的日志等级转为字符串，用于保存进leftbuffer
    string ToString(int level)
    {
        switch (level)
        {
        case Info:
            return "Info";

        case Warning:
            return "Warning";

        case Error:
            return "Error";

        case Fatal:
            return "Fatal";

        case Debug:
            return "Debug";

        default:
            break;
        }
    }

    void operator()(int level /*日志等级*/, const char *format /*自定义内容*/, ...)
    {
        time_t t = time(nullptr);
        struct tm *ctime = localtime(&t); // 获取时间

        char leftbuffer[SIZE];
        string slevel = ToString(level);

        snprintf(leftbuffer, sizeof(leftbuffer), "[%s][%d-%d-%d => %d:%d:%d] ",
                 slevel.c_str(), ctime->tm_year + 1900, ctime->tm_mon + 1, ctime->tm_mday,
                 ctime->tm_hour, ctime->tm_min, ctime->tm_sec);
        // snprintf(leftbuffer, sizeof(leftbuffer), "[%s][111:1111] ",
        //          slevel.c_str());

        va_list s;           // 定义列表
        va_start(s, format); // 初始化，format用于获取可变部分的首地址
        char rightbuffer[SIZE];
        vsnprintf(rightbuffer, sizeof(rightbuffer), format, s);
        va_end(s);

        char logtxt[SIZE * 2];
        snprintf(logtxt, sizeof(logtxt), "%s %s\n", leftbuffer, rightbuffer);

        //cout << logtxt << endl; // 暂时打印输出
        Printlog(level, logtxt);
    }



    void Printlog(int level, const string &logtxt)
    {
        switch(logmode)
        {
            case Print:
                cout << logtxt << endl;
                break;
            case InputFile:
                PutFile(LogFile,logtxt);
                break;
            case ClassFile:
                Class(level, logtxt);
        }
    }

    void PutFile(const string &logname, const string &logtxt)//将日志信息全部存放在一个文件里
    {
        string _logname = path + logname ;
        int fd = open(_logname.c_str(), O_WRONLY|O_CREAT|O_APPEND);//可写可新创建可追加
        int n = write(fd,logtxt.c_str(),logtxt.size());
        close(fd);
    }

    void Class(int level, const string &logtxt)//向不同的文件内写入不同的日志信息
    {   
        string filename = LogFile;
        filename += ".";
        filename += ToString(level);
        PutFile(filename.c_str(), logtxt);
    }

private:
    int logmode;//日志信息的输出模式
    string path;//存放日志信息的位置

};
